package com.atguigu.tingshu.account.service.impl;

import com.atguigu.tingshu.account.mapper.UserAccountDetailMapper;
import com.atguigu.tingshu.account.mapper.UserAccountMapper;
import com.atguigu.tingshu.account.service.UserAccountService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.utils.ThrowUtil;
import com.atguigu.tingshu.model.account.UserAccount;
import com.atguigu.tingshu.model.account.UserAccountDetail;
import com.atguigu.tingshu.vo.account.AccountDeductVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Slf4j
@Service
@SuppressWarnings({ "all" })
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {

    @Autowired
    private UserAccountMapper userAccountMapper;

    @Autowired
    private UserAccountDetailMapper userAccountDetailMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initUserAccount(Long userId) {
        log.info("开始初始化用户账户 - userId: {}", userId);
        try {
            // 1. 检查账户是否已存在
            LambdaQueryWrapper<UserAccount> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserAccount::getUserId, userId);
            UserAccount existAccount = userAccountMapper.selectOne(queryWrapper);
            if (existAccount != null) {
                log.warn("用户账户已存在，跳过初始化 - userId: {}", userId);
                return;
            }
            // 2. 创建用户账户
            UserAccount userAccount = new UserAccount();
            userAccount.setUserId(userId);
            userAccount.setTotalAmount(BigDecimal.ZERO);
            userAccount.setLockAmount(BigDecimal.ZERO);
            userAccount.setAvailableAmount(BigDecimal.ZERO);
            userAccount.setTotalIncomeAmount(BigDecimal.ZERO);
            userAccount.setTotalPayAmount(BigDecimal.ZERO);
            userAccountMapper.insert(userAccount);
            log.info("用户账户创建成功 - userId: {}, accountId: {}", userId, userAccount.getId());
            // 3. 添加账户初始化明细记录（解锁账户）
            UserAccountDetail accountDetail = new UserAccountDetail();
            accountDetail.setUserId(userId);
            accountDetail.setTitle("账户初始化");
            accountDetail.setTradeType(SystemConstant.ACCOUNT_TRADE_TYPE_UNLOCK); // 1203-解锁
            accountDetail.setAmount(BigDecimal.ZERO);
            accountDetail.setOrderNo("INIT_" + userId);
            userAccountDetailMapper.insert(accountDetail);
            log.info("账户初始化明细记录创建成功 - userId: {}, detailId: {}", userId, accountDetail.getId());
            log.info("用户账户初始化完成 - userId: {}", userId);
        } catch (Exception e) {
            log.error("初始化用户账户失败 - userId: {}", userId, e);
            throw new RuntimeException("初始化用户账户失败", e);
        }
    }

    @Override
    public BigDecimal getAvailableAmount(Long userId) {
        log.info("查询用户可用余额 - userId: {}", userId);

        LambdaQueryWrapper<UserAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserAccount::getUserId, userId);
        UserAccount userAccount = userAccountMapper.selectOne(queryWrapper);

        if (userAccount == null) {
            log.warn("用户账户不存在 - userId: {}", userId);
            return BigDecimal.ZERO;
        }

        BigDecimal availableAmount = userAccount.getAvailableAmount();
        log.info("查询用户可用余额成功 - userId: {}, availableAmount: {}", userId, availableAmount);

        return availableAmount != null ? availableAmount : BigDecimal.ZERO;
    }

    @Override
    // TODO 分布式事务需要删除
    @Transactional(rollbackFor = Exception.class)
    public void checkAndDeduct(AccountDeductVo accountDeductVo) {
        Long userId = accountDeductVo.getUserId();
        String orderNo = accountDeductVo.getOrderNo();
        BigDecimal deductAmount = accountDeductVo.getAmount();
        String content = accountDeductVo.getContent();
        log.info("开始检查并扣减账户余额 - userId: {}, orderNo: {}, amount: {}, content: {}",
                userId, orderNo, deductAmount, content);
        // 1. 参数校验
        ThrowUtil.throwIf(userId == null, "用户ID不能为空");
        ThrowUtil.throwIf(orderNo == null || orderNo.isEmpty(), "订单号不能为空");
        ThrowUtil.throwIf(deductAmount == null || deductAmount.compareTo(BigDecimal.ZERO) <= 0,
                "扣减金额必须大于0");
        // 2. 使用悲观锁查询用户账户，同时判断余额是否足够
        UserAccount userAccount = userAccountMapper.selectForUpdateWithAmount(userId, deductAmount);
        ThrowUtil.throwIf(userAccount == null, "用户账户不存在或余额不足");
        BigDecimal availableAmount = userAccount.getAvailableAmount();
        log.info("获取用户账户信息 - userId: {}, availableAmount: {}, deductAmount: {}",
                userId, availableAmount, deductAmount);
        // 3. 计算扣减后的金额
        BigDecimal newAvailableAmount = availableAmount.subtract(deductAmount);
        BigDecimal newTotalAmount = userAccount.getTotalAmount().subtract(deductAmount);
        BigDecimal newTotalPayAmount = userAccount.getTotalPayAmount().add(deductAmount);
        // 4. 更新账户金额
        userAccount.setAvailableAmount(newAvailableAmount);
        userAccount.setTotalAmount(newTotalAmount);
        userAccount.setTotalPayAmount(newTotalPayAmount);
        userAccountMapper.updateById(userAccount);
        log.info("账户余额扣减成功 - userId: {}, deductAmount: {}, newAvailableAmount: {}",
                userId, deductAmount, newAvailableAmount);
        log.info("账户余额检查并扣减完成 - userId: {}, orderNo: {}", userId, orderNo);
        // 5. 添加账户变动明细记录（支付）
        userAccountDetailMapper.saveUserAccountDetail(
                accountDeductVo.getUserId(),
                accountDeductVo.getContent(),
                SystemConstant.ACCOUNT_TRADE_TYPE_MINUS,
                accountDeductVo.getAmount(),
                accountDeductVo.getOrderNo());
    }
}
